前言
上一篇文章中介绍了自定义View的基本流程,今天我们仍然跟随洋神脚步学习自定义View,本篇文章参考自洋神的 Android 自定义View (三) 圆环交替 等待效果一文,有兴趣的可以去洋神的博客看看哈!
举例
自定义View流程回顾
上一篇文章中介绍了下自定义View的流程,在本篇文章中我们仍然将这4个步骤列出来加深印象:
- 自定义View的属性
- 在View的构造方法中获得自定义的属性
- 重写onMeasure
- 重写onDraw
下面我们按照这4个步骤一步步完成我们的自定义View。
自定义View的属性
在工程目录下的res/values子目录下建立一个attrs.xml文件,在里面定义我们需要的属性:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="firstColor" format="color"/> <attr name="secondColor" format="color"/> <attr name="circleWidth" format="dimension"/> <attr name="speed" format="integer"/> <declare-styleable name="CustomView"> <attr name="firstColor"/> <attr name="secondColor"/> <attr name="circleWidth"/> <attr name="speed"/> </declare-styleable> </resources>
|
如上面这段代码,我们定义了4个属性,分别是第一个圆环的颜色、第二个圆环的颜色、圆环的宽度以及圆环更新的速度,然后我们就可以在layout布局文件中这样使用我们的自定义View及自定义属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.glemontree.customview04.MainActivity"> <com.glemontree.customview04.CustomView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
|
这里我没有添加自定义属性,全都使用的默认属性,如果你有兴趣,可以在layout布局文件中的CustomView
子结点下添加app:xxx="xxx"
来使用自定义属性。
在View的构造方法中获取自定义属性
紧接着我们可以在自定义View的构造方法中获取自定义的属性,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0); mFirstColor = a.getColor(R.styleable.CustomView_firstColor, Color.GREEN); mSecondColor = a.getColor(R.styleable.CustomView_secondColor, Color.RED); mCircleWidth = a.getDimensionPixelOffset(R.styleable.CustomView_circleWidth, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics())); mSpeed = a.getInt(R.styleable.CustomView_speed, 20); a.recycle(); mPaint = new Paint(); new Thread() { public void run() { while (true) { mProgress++; if (mProgress == 360) { mProgress = 0; if (!mIsNext) { mIsNext = true; } else { mIsNext = false; } } postInvalidate(); try { Thread.sleep(mSpeed); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }
|
在View的构造方法中我们分别获取了我们自定义的4个属性,并且设置了默认值,这样即使在layout布局文件中不设置这4个自定义属性,仍然可以保证有值。
在构造方法中还开启了一个线程,这个线程主要的目的就是更新mProgress
并且刷新界面,mProgress
每增加1,就刷新界面一次,刷新界面是通过postInvalidate()
方法来实现的。
因为这里并不需要onMeasure()
操作,因此省去onMeasure()
的实现,我们直接看onDraw()
函数。
重写onDraw
onDraw()
函数的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| @Override protected void onDraw(Canvas canvas) { int centre = getWidth() / 2; int radius = centre - mCircleWidth / 2; mPaint.setStrokeWidth(mCircleWidth); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); if (!mIsNext) { mPaint.setColor(mFirstColor); canvas.drawCircle(centre, centre, radius, mPaint); mPaint.setColor(mSecondColor); canvas.drawArc(oval, -90, mProgress, false, mPaint); } else { mPaint.setColor(mSecondColor); canvas.drawCircle(centre, centre, radius, mPaint); mPaint.setColor(mFirstColor); canvas.drawArc(oval, -90, mProgress, false, mPaint); } }
|
其实也没啥特别要说的,就是绘制圆环和圆弧,下面我想介绍下drawArc()
函数。
`drawArc()
函数的原型如下:
1
| public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
|
其各个参数的含义如下:
- oval:指定圆弧的外轮廓矩形区域
- startAngle:圆弧起始角度,单位为度
- sweepAngle:圆弧扫过的角度,顺时针方向,单位为度
- useCenter:当为true时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形
- paint:绘制圆弧的画笔
第一个参数oval
我纠结了蛮久,一直没搞懂是什么意思,其实呢,就是圆弧的外切圆,比如在我们的程序中:
1
| RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);
|
绘制的矩形正好是圆弧的外切矩形,在上面这段程序中你可以取消最后一行的注释,查看绘制的矩形到底是什么样的。
总结
其实我是想上一张动图的,但是尼玛使用GifCam录制动图得到的动图总是颜色凌乱,还没搞懂,等我搞懂了搞张图上来。